package com.ht.WeNas.service;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ht.WeNas.config.WeNasCustom;
import com.ht.WeNas.dao.repo.UserRepo;
import com.ht.WeNas.data.dto.UserDto;
import com.ht.WeNas.data.entity.User;
import com.ht.WeNas.data.enumObj.UserType;
import com.ht.WeNas.data.vo.user.CreateUserForm;
import com.ht.WeNas.data.vo.user.UserLoginForm;
import com.ht.WeNas.utils.MyIdUtil;
import com.ht.WeNas.utils.ThreadLocalUtil;
import com.ht.WeNas.utils.TokenUtil;
import com.ht.WeNas.utils.UserPwdUtil;
import com.ht.WeNas.utils.exceptions.MessageException;
import com.ht.WeNas.utils.exceptions.UserNotLoginException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
public class UserService {
    private final WeNasCustom weNasCustom;
    private final UserRepo userRepo;
    
    public UserService(WeNasCustom weNasCustom, UserRepo userRepo) {
        this.weNasCustom = weNasCustom;
        this.userRepo = userRepo;
    }
    
    public String login(UserLoginForm userLoginForm) {
        String username = userLoginForm.getUsername();
        User userByName = userRepo.getUserByName(username);
        if (userByName == null || !UserPwdUtil.matches(userByName.getPassword(), userLoginForm.getPassword())) {
            throw new MessageException("用户名或密码错误");
        }
        return TokenUtil.createToken(new UserDto(userByName));
    }

    @Transactional
    public UserDto createUser(CreateUserForm createUserForm) {
        String username = createUserForm.getUsername();
        String password = createUserForm.getPassword();
        if (StrUtil.isBlankIfStr(username) || StrUtil.isBlankIfStr(password)) {
            return null;
        }
        // 检查用户名是否重复
        var wrapper = Wrappers.lambdaQuery(User.class).eq(User::getUsername, username);
        if (userRepo.exists(wrapper)) {
            throw new MessageException("用户已存在");
        }
        // 组装User数据
        User user = new User();
        user.setId(MyIdUtil.nextId());
        user.setUsername(username);
        user.setPassword(UserPwdUtil.encode(password));
        user.setUserType(UserType.User);
        userRepo.save(user);
        // 二次校验
        User newUser = userRepo.getUserById(user.getId());
        if (newUser == null) {
            return null;
        }
        return new UserDto(newUser);
    }
    
    public User getUserById(long id) {
        return userRepo.getUserById(id);
    }

    /**
     * 修改用户类型，只能由管理员调用
     * @param userId 目标用户id
     * @param userType 用户类型
     */
    public void changeUserType(long userId, UserType userType) {
        User user = userRepo.getUserById(userId);
        if (user == null) {
            throw new MessageException("修改的用户不存在");
        }
        if (user.getUserType() == userType) {
            return;
        }
        user.setUserType(userType);
        userRepo.updateById(user);
    }
    
    public void changePassword(UserDto dto, String oldPwd, String newPwd) {
        User user = userRepo.getUserById(Long.parseLong(dto.getId()));
        if (user == null) {
            throw new MessageException("用户不存在");
        }
        if (!UserPwdUtil.matches(user.getPassword(), oldPwd)) {
            throw new MessageException("新旧密码不一致");
        }
        user.setPassword(UserPwdUtil.encode(newPwd));
        userRepo.updateById(user);
    }
    
    public void deleteUser(long id) throws UserNotLoginException {
        if (id == weNasCustom.getDefaultUserId()) {
            throw new MessageException("默认用户无法删除");
        }
        UserDto userDto = ThreadLocalUtil.getUserDto();
        if (userDto.getId().equals(String.valueOf(id)) && userDto.getUserType() != UserType.Admin) {
            // 删除对象既不是自己，自己也不是管理员
            throw new MessageException("无权删除");
        }
        userRepo.deleteUser(id);
    }
    
    /**
     * 插入默认用户<br/>
     * <strong>会覆盖默认用户的设置，需要严格限制</strong>
     */
    public void insertDefaultUser() {
        User user = new User();
        user.setId(weNasCustom.getDefaultUserId());
        user.setUserType(UserType.Admin);
        user.setUsername(weNasCustom.getDefaultUserName());
        user.setPassword(UserPwdUtil.encode(weNasCustom.getDefaultUserPwd()));
        if (this.userRepo.exists(
                new LambdaQueryWrapper<>(User.class).eq(User::getId, user.getId())
        )) {
            return;
        }
        this.userRepo.save(user);
    }
}
